package com.weixing.mall.provider.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.weixing.mall.base.constant.GlobalConstant;
import com.weixing.mall.base.exception.BusinessException;
import com.weixing.mall.base.utils.EnumUtil;
import com.weixing.mall.base.wrapper.Result;
import com.weixing.mall.base.wrapper.ResultUtil;
import com.weixing.mall.core.enums.OrderAppTagEnum;
import com.weixing.mall.core.enums.OrderSysTagEnum;
import com.weixing.mall.core.support.auth.SysAuth;
import com.weixing.mall.provider.api.model.CalcProfitPo;
import com.weixing.mall.provider.api.model.dto.ProfitCalcDto;
import com.weixing.mall.provider.api.model.enums.AgentLevelEnum;
import com.weixing.mall.provider.api.model.enums.SettleStateEnum;
import com.weixing.mall.provider.api.model.vo.OrderSettleVo;
import com.weixing.mall.provider.api.model.vo.SysUserEditVo;
import com.weixing.mall.provider.api.service.AgentProfitFeign;
import com.weixing.mall.provider.api.service.SysConfigServiceFeign;
import com.weixing.mall.provider.manager.ProfitManager;
import com.weixing.mall.provider.mapper.OrderOperationMapper;
import com.weixing.mall.provider.model.domain.Order;
import com.weixing.mall.provider.model.domain.OrderAgent;
import com.weixing.mall.provider.model.domain.OrderLog;
import com.weixing.mall.provider.model.domain.OrderOperation;
import com.weixing.mall.provider.model.dto.NosuppllyOperationDto;
import com.weixing.mall.provider.model.dto.OrderAuditDto;
import com.weixing.mall.provider.model.dto.OrderOperationDto;
import com.weixing.mall.provider.model.enums.*;
import com.weixing.mall.provider.model.vo.OrderOperationVo;
import com.weixing.mall.provider.service.IOrderAgentService;
import com.weixing.mall.provider.service.IOrderLogService;
import com.weixing.mall.provider.service.IOrderOperationService;
import com.weixing.mall.provider.service.IOrderService;
import com.weixing.mall.provider.util.OrderUtil;
import jodd.util.ArraysUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * <p>
 * 订单模块-订单操作记录表 服务实现类
 * </p>
 *
 * @author Small
 * @since 2019-11-20
 */
@Slf4j
@Service
public class OrderOperationServiceImpl extends ServiceImpl<OrderOperationMapper, OrderOperation> implements IOrderOperationService {
    @Autowired
    private SysConfigServiceFeign sysConfigService;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private AgentProfitFeign agentProfitFeign;
    @Autowired
    private IOrderAgentService orderAgentService;
    @Autowired
    private ProfitManager profitManager;
    @Autowired
    private IOrderLogService orderLogService;

    @Override
    public List<OrderOperationVo> selectList(Long orderId) {
        return baseMapper.selectList(orderId);
    }

    @Override
    public void save(OrderOperationDto orderOperationDto) {

        OrderOperation orderOperation = new OrderOperation();

        //操作员id
        orderOperation.setOperatorId(orderOperationDto.getOperatorId());
        //订单id
        orderOperation.setOrderId(orderOperationDto.getOrderId());
        //操作员类型
        if (orderOperationDto.getOperatorType() != null) {
            orderOperation.setOperateType(orderOperationDto.getOperatorType().getValue());
        }
        //操作员角色
        orderOperation.setOperatorRole(orderOperationDto.getOperatorRole());
        //操作员
        orderOperation.setOperator(orderOperationDto.getOperator());
        orderOperation.setRemark(orderOperationDto.getRemark());
        //操作内容
        orderOperation.setOperation(orderOperationDto.getOperation());
        //创建时间
        orderOperation.setCreatedTime(new Date());
        save(orderOperation);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void nosuppllyOperationSave(NosuppllyOperationDto nosuppllyOperationDto, SysAuth auth) {

        Long id = nosuppllyOperationDto.getOrderId();
        Order order = orderService.getById(id);
        if (ObjectUtil.isEmpty(order)) {
            throw new BusinessException("操作订单信息不存在");
        }
        Integer nosuppllyAudit = null;
        if (nosuppllyOperationDto.getNosuppllyAudit() != null) {
            nosuppllyAudit = nosuppllyOperationDto.getNosuppllyAudit().getValue();
        }
        Integer sysTag = null;
        Integer appTag = null;
        if (order.getItemStatus().equals(ProductStatusEnum.STATUS6.getValue())) {
            sysTag = OrderSysTagEnum.DHK_TAG_402.getValue();
            appTag = OrderAppTagEnum.DHK_TAG_402.getValue();
        } else if (order.getItemStatus().equals(ProductStatusEnum.STATUS7.getValue())) {
            sysTag = OrderSysTagEnum.QXK_TAG_401.getValue();
            appTag = OrderAppTagEnum.QXK_TAG_401.getValue();
        }
        //1 客服修改订单表里面的断货审核状态并填入时间
        order.setNosuppllyAudit(nosuppllyAudit);
        order.setNosuppllyTime(new Date());
        if (sysTag != null && appTag != null) {
            order.setSysTag(sysTag);
            order.setAppTag(appTag);
        }
        orderService.updateById(order);
        //orderMapper.updateNoSuppllyAudit(id, nosuppllyAudit, new Date());
        //回滚代理商返利
        Result result = agentProfitFeign.unProfit(id);
        if (!result.isSuccess()) {
            throw new BusinessException("调用回滚返利服务失败");
        }
        if (order.getItemStatus().equals(ProductStatusEnum.STATUS6.getValue())) {
            //订单退货操作日志
            orderLogService.addOrderLog(id,OrderLogTypeEnum.STOCK_OUT.getValue(),auth.getUid(),auth.getRealName());
        } else if (order.getItemStatus().equals(ProductStatusEnum.STATUS7.getValue())) {
            //订单退货操作日志
            orderLogService.addOrderLog(id,OrderLogTypeEnum.CANCEL.getValue(),auth.getUid(),auth.getRealName());
        }


        OrderOperation orderOperation = new OrderOperation();
        //2 客服记录断货操作
        SysUserEditVo sysUserEditVo = sysConfigService.getUserById(auth.getUid()).getData();
        if (sysUserEditVo != null) {
            //操作人id
            orderOperation.setOperatorId(sysUserEditVo.getId());
            //操作人
            orderOperation.setOperator(sysUserEditVo.getRealName());
        }
        //订单id
        orderOperation.setOrderId(nosuppllyOperationDto.getOrderId());
        //备注
        orderOperation.setRemark(nosuppllyOperationDto.getRemark());
        //操作人类型
        if (nosuppllyOperationDto.getOperatorType() != null) {
            orderOperation.setOperateType(nosuppllyOperationDto.getOperatorType().getValue());
        }
        //操作内容
        if (nosuppllyOperationDto.getNosuppllyAudit() != null) {
            orderOperation.setOperation(nosuppllyOperationDto.getNosuppllyAudit().getDesp());
        }
        //创建时间
        orderOperation.setCreatedTime(new Date());
        //保存客服断货操作
        save(orderOperation);
    }

    /**
     * 方法描述: 代理商订单审核
     *
     * @param orderAuditDto  审核参数
     * @date  2020/2/26 15:07
     */
    @Override
    public void agentAudit(OrderAuditDto orderAuditDto, long agentId, String agentName) {
        Order order = orderService.getById(orderAuditDto.getOrderId());
        if (order.getAuditor().longValue() != agentId) {
            throw new BusinessException("当前审核节点不在您这里，不能审核");
        }
        // 解析订单代理认领树
        List<CalcProfitPo> calcProfitPos = OrderUtil.parseTreePath(order.getAgentCliamLine());
        CalcProfitPo own = null;
        int ownTreePath = -1;
        int length = calcProfitPos.size();
        for (int i = 0; i < length; i++) {
            CalcProfitPo calcProfitPo = calcProfitPos.get(i);
            long aId = calcProfitPo.getAgentId();
            // 计算出当前登录的代理商
            if (null == own && agentId == aId) {
                own = calcProfitPo;
                ownTreePath = i;
            }
        }

        if (null == own) {
            throw new BusinessException("当前订单不属于您，您不能够审核");
        }

        // 记录订单审核记录
        createOrderOpera(orderAuditDto, agentId, agentName, own);
        // 修改订单信息
        if (AuditStateEnum.REJECT.equals(orderAuditDto.getAuditState())) {
            // 会员下的单子都不能拒绝
            if (OrderFromEnum.MEMBER.getValue().equals(order.getOrderFrom())) {
                throw new BusinessException("会员正价订单不能拒绝");
            } else if (OrderFromEnum.AGENT.getValue().equals(order.getOrderFrom())) {
                // 代理下的单子如果拒绝就直接表示为 已拒绝状态  需求确认日期：20200623
                order.setOrderStatus(OrderStateEnum.REJECT.getValue());
                order.setSysTag(OrderSysTagEnum.YJJ_TAG_204.getValue());
                order.setAppTag(OrderAppTagEnum.YJJ_TAG_201.getValue());
            }
        } else {
            int afterAgentIndex = ownTreePath + 1;
            if (afterAgentIndex > length - 1) {
                // 流转到客服部
                order.setAuditDept(AuditDeptEnum.SERVICE_DEPT.getValue());
                order.setAuditor(order.getCustomerId());
                order.setAuditStatus(OrderAuditStateEnum.AGENT_AUDIT_SUCCESS.getValue());
            } else {
                CalcProfitPo calcProfitPo1 = calcProfitPos.get(afterAgentIndex);
                order.setAuditDept(AuditDeptEnum.AGENT.getValue());
                order.setAuditor(calcProfitPo1.getAgentId());
                // 跟新下一个待审核代理获利表中结算状态为  待上交
                updateOrderAgent(order.getId(), calcProfitPo1.getAgentId(), GlobalConstant.PROFIT_SETTLE_STATE_NEEDUP);
            }
            order.setOrderStatus(OrderStateEnum.AUDITING.getValue());
            order.setSysTag(OrderSysTagEnum.SHZ_TAG_104.getValue());
            order.setAppTag(OrderAppTagEnum.SHZ_TAG_102.getValue());
            // 跟新代理获利表中结算状态为  已上交
            updateOrderAgent(order.getId(), agentId, GlobalConstant.PROFIT_SETTLE_STATE_HASUP);
        }
        // 记录代理已审核列表
        String orderAuditorList = order.getOrderAuditorList();
        String[] agentAuditIds = orderAuditorList.split(GlobalConstant.symbol.COMMA);
        if (!ArraysUtil.contains(agentAuditIds, String.valueOf(own.getAgentId()))) {
            orderAuditorList = orderAuditorList + GlobalConstant.symbol.COMMA + own.getAgentId();
        }
        order.setOrderAuditorList(orderAuditorList);
        orderService.updateById(order);
    }


    private void updateOrderAgent(long orderId, long agentId, int state) {
        // 跟新下一个待审核代理获利表中结算状态为  待上交
        OrderAgent orderAgent = orderAgentService.findByOrderIdAndAgentId(orderId, agentId);
        orderAgent.setSettleState(state);
        orderAgentService.updateById(orderAgent);
    }

    private void createOrderOpera(OrderAuditDto orderAuditDto, long agentId, String agentName, CalcProfitPo own) {
        OrderOperation orderOpera = new OrderOperation();
        orderOpera.setOrderId(orderAuditDto.getOrderId());
        orderOpera.setOperatorId(agentId);
        orderOpera.setOperator(agentName);
        orderOpera.setRoleLebel(EnumUtil.getIEnum(AgentLevelEnum.class, own.getAgentLevel()).getDesp());
        orderOpera.setOperatorRole(OperatorRoleEnum.AGENT.getValue());
        orderOpera.setOperateType(OperateTypeEnum.AUDIT.getValue());
        orderOpera.setOperation(AuditStateEnum.AGGREE.equals(orderAuditDto.getAuditState()) ? "审核通过" : "审核失败");
        orderOpera.setRemark(orderAuditDto.getRemark());
        save(orderOpera);
    }


    /**
     * 方法描述:客服审核
     * @Author Small
     * @param orderAuditDto
     * @param auth
     * @Date 2020/3/5 10:24
     * @return void
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void customerAudit(OrderAuditDto orderAuditDto, SysAuth auth) {
        //当前登陆人id
        Order order = orderService.getById(orderAuditDto.getOrderId());

        if (OrderAuditStateEnum.KEFU_AUDITING.getValue().equals(order.getAuditStatus()) ||
                OrderAuditStateEnum.KEFU_AUDIT_REFUSE.getValue().equals(order.getAuditStatus())) {
            throw new BusinessException("订单已审核，请勿重复审核");
        }
        //客服审核通过
        if (AuditStateEnum.AGGREE.equals(orderAuditDto.getAuditState())) {
            // 修改订单状态；客服审核通过 订单状态为待封单 6
            order.setOrderStatus(OrderStateEnum.AUDIT_SUCCESS.getValue());
            order.setSettleState(SettleStateEnum.RAISE_SETTLE.getValue());
            order.setAuditStatus(OrderAuditStateEnum.KEFU_AUDITING.getValue());
            order.setSysTag(OrderSysTagEnum.YSH_TAG_105.getValue());
            order.setAppTag(OrderAppTagEnum.YSH_TAG_103.getValue());
            order.setAuditTime(new Date());
            order.setKefuRemark(orderAuditDto.getRemark());

        } else {
            if (OrderFromEnum.MEMBER.getValue().equals(order.getOrderFrom())
                    || OrderFromEnum.CUSTOMER.getValue().equals(order.getOrderFrom())) {
                // 按照客户发的订单状态对应表
                order.setFrontOrderStatus(OrderFrontStateEnum.WAIT_SHIP.getValue());
            }
            order.setAuditStatus(OrderAuditStateEnum.KEFU_AUDIT_REFUSE.getValue());
            order.setOrderStatus(OrderStateEnum.REJECT.getValue());
            order.setSysTag(OrderSysTagEnum.YJJ_TAG_204.getValue());
            order.setAppTag(OrderAppTagEnum.YJJ_TAG_201.getValue());
            order.setKefuRemark(orderAuditDto.getRemark());
        }
        // 如果是未认领订单，审核后订单自动跟客服绑定
        if (null == order.getCustomerId()) {
            order.setCustomerId(auth.getUid());
            order.setCustomerName(auth.getRealName());
            order.setAuditStatus(OrderAuditStateEnum.KEFU_AUDITING.getValue());
            List<OrderAgent> list = profitManager.calcProfit(order, null, null);
            if (CollUtil.isNotEmpty(list)) {
                orderAgentService.saveBatch(list);
            }
        }
        // 更新订单
        orderService.updateById(order);
        // 计算代理商收益采用异步通知模式
        if (AuditStateEnum.AGGREE.equals(orderAuditDto.getAuditState())) {
            //  计算代理获利
            this.agentProfitCalc(order);

            // 记录订单日志
            createOrderLog(orderAuditDto, auth);
        }
        // 记录订单操作记录
        OrderOperation orderOpera = new OrderOperation();
        orderOpera.setOrderId(orderAuditDto.getOrderId());
        orderOpera.setOperatorId(auth.getUid());
        orderOpera.setOperator(auth.getRealName());
        orderOpera.setRoleLebel("客服");
        orderOpera.setOperatorRole(OperatorRoleEnum.KEFU.getValue());
        orderOpera.setOperateType(OperateTypeEnum.AUDIT.getValue());
        orderOpera.setOperation(AuditStateEnum.AGGREE.equals(orderAuditDto.getAuditState()) ? "审核通过" : "审核失败");
        orderOpera.setRemark(orderAuditDto.getRemark());
        save(orderOpera);
    }

    private void createOrderLog(OrderAuditDto orderAuditDto, SysAuth auth) {
        OrderLog log = new OrderLog();
        log.setOrderId(orderAuditDto.getOrderId());
        log.setLogType(1);
        log.setCreatedTime(new Date());
        log.setOperatorId(auth.getUid());
        log.setOperatorName(auth.getRealName());
        orderLogService.save(log);
    }

    /**
     * 方法描述: 订单结算状态人工回调
     * @Author Small
     * @param orderId
     * @Date 2020/3/6 14:57
     * @return com.weixing.mall.base.wrapper.Result
     */
    @Override
    public Result settleQuery(Long orderId) {
        Order order = orderService.getById(orderId);
        if (null == order) {
            return ResultUtil.error("订单不存在");
        }
        int orderSettleState = order.getSettleState().intValue();
        if (SettleStateEnum.NOT_SETTLE.getValue().intValue() == orderSettleState) {
            return ResultUtil.error("订单尚未发起结算");
        }
        if (SettleStateEnum.SETTLED.getValue().intValue() == orderSettleState) {
            return ResultUtil.success("订单已结算");
        }
        if (SettleStateEnum.RAISE_SETTLE.getValue().intValue() == orderSettleState) {
            // 调用agent服务查询订单结算状态
            ProfitCalcDto profitCalcDto = getProfitCalcDto(order);
            Result<OrderSettleVo> orderSettleDtoResult = agentProfitFeign.orderSettleQuery(profitCalcDto);
            if (!orderSettleDtoResult.isSuccess()) {
                return orderSettleDtoResult;
            } else {
                OrderSettleVo orderSettleDto = orderSettleDtoResult.getData();
                if (GlobalConstant.SUCCESS.equals(orderSettleDto.getSettleState())) {
                    order.setSettleState(SettleStateEnum.SETTLED.getValue());
                    orderService.updateById(order);
                    return ResultUtil.success("订单已结算");
                } else {
                    order.setSettleState(SettleStateEnum.SETTLE_FAILD.getValue());
                    orderService.updateById(order);
                    return ResultUtil.success("订单结算失败");
                }
            }
        }
        return ResultUtil.error("查询失败");
    }

    /**
     * 方法描述: 结算失败订单重新发起结算
     * @Author Small
     * @param orderId
     * @Date 2020/3/6 15:10
     * @return com.weixing.mall.base.wrapper.Result
     */
    @Override
    public Result reSettle(Long orderId) {
        Order order = orderService.getById(orderId);
        if (null == order) {
            return ResultUtil.error("订单不存在");
        }
        int orderSettleState = order.getSettleState().intValue();
        if (SettleStateEnum.SETTLE_FAILD.getValue().intValue() != orderSettleState) {
            return ResultUtil.error("订单状态不是结算失败状态，不能够重新发起结算");
        }
        // 调用agent服务查询订单结算状态
        ProfitCalcDto profitCalcDto = getProfitCalcDto(order);
        agentProfitFeign.calcProfit(profitCalcDto);
        return ResultUtil.success("结算请求已发起，请稍后查看结算结果");
    }


    /**
     * 方法描述: 代理商收益计算
     * @Author Small
     * @param order
     * @Date 2020/3/5 11:34
     * @return java.lang.Void
     */
    private void agentProfitCalc(Order order) {
        ProfitCalcDto profitCalc = getProfitCalcDto(order);
        if (null == order.getActId()) {
            log.debug("客服审核通过，执行代理获利计算操作，订单编号{}", order.getOrderSn());

            Result result = agentProfitFeign.calcProfit(profitCalc);
            log.debug("代理获利计算结果", result.isSuccess());

            if (!result.isSuccess()) {
                throw new BusinessException("审核失败");
            } else {
                order.setSettleState(SettleStateEnum.SETTLED.getValue());
            }

        }
    }

    private ProfitCalcDto getProfitCalcDto(Order order) {
        ProfitCalcDto profitCalc = new ProfitCalcDto();
        profitCalc.setOrderGmtTime(order.getCreatedTime());
        profitCalc.setOrderAuditTime(order.getAuditTime());
        profitCalc.setKefuId(order.getCustomerId());
        profitCalc.setKefu(order.getCustomerName());
        profitCalc.setAgentId(order.getAgentId());
        profitCalc.setOrderId(order.getId());
        profitCalc.setActId(order.getActId());
        profitCalc.setOrderSn(order.getOrderSn());
        // 下单来源
        return profitCalc;
    }
}
